Peter pointed out that stringByExpandingTildeInPath was unneeded since path returns...
[adiumx.git] / Frameworks / Adium Framework / Source / DCJoinChatViewController.m
blob70f6d148e075d8f1ec9a6764bc41f183adb42500
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  * 
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import <Adium/AIAccount.h>
18 #import <Adium/AIChat.h>
19 #import <Adium/AIContactControllerProtocol.h>
20 #import <Adium/AIChatControllerProtocol.h>
21 #import <Adium/AIService.h>
22 #import <Adium/AIListContact.h>
23 #import <Adium/AIMetaContact.h>
24 #import <Adium/DCJoinChatViewController.h>
25 #import <AIUtilities/AIStringAdditions.h>
27 @interface DCJoinChatViewController (PRIVATE)
28 - (NSString *)impliedCompletion:(NSString *)aString;
29 @end
31 @implementation DCJoinChatViewController
33 //Create a new join chat view
34 + (DCJoinChatViewController *)joinChatView
36         return [[[self alloc] init] autorelease];
39 //Init
40 - (id)init
42     if ((self = [super init]))
43         {
44                 chat = nil;
45                 delegate = nil;
46                 
47                 NSString        *nibName = [self nibName];
48                 if (nibName)
49                 {
50                         [NSBundle loadNibNamed:nibName owner:self];
51                 }
52         }
53         
54     return self;
57 - (void)dealloc
59         [view release]; view = nil;
60         [account release];
62         [super dealloc];
65 - (NSView *)view
67         return view;
70 //Stubs for subclasses
71 - (NSString *)nibName {
72         return nil;
74 - (void)joinChatWithAccount:(AIAccount *)inAccount
76         
79 - (void)configureForAccount:(AIAccount *)inAccount
80
81         if (inAccount != account) {
82                 [account release];
83                 account = [inAccount retain]; 
84         }
87 - (NSString *)impliedCompletion:(NSString *)aString
89         return aString;
93 /*!
94  * @brief Join a group chat with given information
95  *
96  * @param inName The name of the chat
97  * @param inAccount The account on which to join
98  * @param inInfo Account-specific information which can be used by the account while joining or creating the chat
99  * @param contactsToInvite An array of AIListContacts which will be invited to the chat once Chat_DidOpen is posted for it (once it is open)
100  * @param invitationMessage A message sent to contactsToInvite. Ignored if contactsToInvite is nil.
101  */
102 - (void)doJoinChatWithName:(NSString *)inName
103                                  onAccount:(AIAccount *)inAccount
104                   chatCreationInfo:(NSDictionary *)inInfo 
105                   invitingContacts:(NSArray *)contactsToInvite
106          withInvitationMessage:(NSString *)invitationMessage
108         
109         AILog(@"Creating chatWithName:%@ onAccount:%@ chatCreationInfo:%@",inName,inAccount,inInfo);
110         
111         
112         chat = [[adium chatController] chatWithName:inName
113                                                                          identifier:nil
114                                                                           onAccount:inAccount
115                                                            chatCreationInfo:inInfo];
117         if ([contactsToInvite count]) {
118                 [chat setStatusObject:contactsToInvite forKey:@"ContactsToInvite" notify:NotifyNever];
119                 
120                 if ([invitationMessage length]) {
121                         [chat setStatusObject:invitationMessage forKey:@"InitialInivitationMessage" notify:NotifyNever];
122                 }
123                 
124                 [[adium notificationCenter] addObserver:self selector:@selector(chatDidOpen:) name:Chat_DidOpen object:chat];
125         }
126         
130 //When the chat opens, we are ready to send out our invitations to join it
131 - (void)chatDidOpen:(NSNotification *)notification
133         NSArray *contacts = [chat statusObjectForKey:@"ContactsToInvite"];
134         
135         if (contacts && [contacts count]) {
136                 NSMutableDictionary     *inviteUsersDict;
137                 NSString                        *initialInvitationMessage = [chat statusObjectForKey:@"InitialInivitationMessage"];
138                 
139                 inviteUsersDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[[contacts mutableCopy] autorelease],@"ContactsToInvite",nil];
140                 if (initialInvitationMessage) {
141                         [inviteUsersDict setObject:initialInvitationMessage
142                                                                 forKey:@"InitialInivitationMessage"];
143                 }
144                 AILog(@"scheduling invitation of %@",inviteUsersDict);
145                 [NSTimer scheduledTimerWithTimeInterval:0.01
146                                                                                  target:self
147                                                                            selector:@selector(inviteUsers:)
148                                                                            userInfo:inviteUsersDict
149                                                                                 repeats:YES];
150         }
151         
152         //The dictionary will retain the ContactsToInvite and InitialInivitationMessage objects;
153         //The timer will retain the dictionary until it is invalidated.
154         [chat setStatusObject:nil forKey:@"ContactsToInvite" notify:NotifyNever];
155         [chat setStatusObject:nil forKey:@"InitialInivitationMessage" notify:NotifyNever];
156         
157         //We are no longer concerned with the opening of this chat.
158         [[adium notificationCenter] removeObserver:self name:Chat_DidOpen object:chat];
162  * @brief Timer method to invite contacts to a chat
163  * 
164  * This is called repeatedly by the scheduled timer until all users have been invited to the chat.
165  * This is done incrementally to prevent beachballing if the process is slow and a large number of users are invited.
166  */
167 - (void)inviteUsers:(NSTimer *)inTimer
169         NSMutableDictionary *userInfo = [inTimer userInfo];
170         NSMutableArray          *contactArray = [userInfo objectForKey:@"ContactsToInvite"];
172         if ([contactArray count]) {
173                 AIListContact *listContact = [[contactArray objectAtIndex:0] retain];
174                 [contactArray removeObjectAtIndex:0];
175                 AILog(@"Inviting %@ to %@", listContact, chat);
177                 [chat inviteListContact:listContact
178                                         withMessage:[userInfo objectForKey:@"InitialInivitationMessage"]];
179                 [listContact release];
181         } else {
182                 [inTimer invalidate];
183         }
187  * @brief Generate an array of AIListContacts given a string and an account
188  * 
189  * @param namesSeparatedByCommas A string in the form @"Contact1,Another Contact,A Third Contact"
190  * @param inAccount The account on which the contacts should be created
191  */
192 - (NSArray *)contactsFromNamesSeparatedByCommas:(NSString *)namesSeparatedByCommas onAccount:(AIAccount *)inAccount;
194         NSMutableArray  *contactsArray = nil;
195         NSArray                 *contactNames;
196         AILog(@"contactsFromNamesSeparatedByCommas:%@ onAccount:%@",namesSeparatedByCommas,inAccount);
197         if ([namesSeparatedByCommas length]) {
199                 contactNames = [namesSeparatedByCommas componentsSeparatedByString:@","];
200                 
201                 if ([contactNames count]) {
202                         NSEnumerator    *enumerator;
203                         NSString                *aContactName, *UID;
204                         AIListContact   *listContact;
205                         
206                         contactsArray = [NSMutableArray array];
207                         
208                         enumerator = [contactNames objectEnumerator];           
209                         while ((aContactName = [enumerator nextObject])) {
210                                                                 
211                                 UID = [[inAccount service] filterUID:[self impliedCompletion:aContactName] removeIgnoredCharacters:YES];
212                                 
213                                 //If the service is not case sensitive, compact the string before proceeding so our UID will be correct
214                                 if (![[inAccount service] caseSensitive]) {
215                                         UID = [UID compactedString];
216                                 }
217                                 
218                                 if ((listContact = [[adium contactController] contactWithService:[inAccount service] 
219                                                                                                                                            account:inAccount 
220                                                                                                                                                    UID:UID])) {
221                                         [contactsArray addObject:listContact];
222                                 }
223                         }
224                 }
225         }
227         AILog(@"contactsArray is %@",contactsArray);
228         return contactsArray;
231 #pragma mark Drag delegate convenience
234  * @brief Find an online contact with the specified service from a unique ID
236  * @result An online AIListContact on service, or nil.
237  */
238 - (AIListContact *)validContact:(NSString *)uniqueID withService:(AIService *)service
240         AIListContact *listContact = nil;
241         AIListObject *listObject = [[adium contactController] existingListObjectWithUniqueID:uniqueID];
242         
243         if ( listObject ) {
244                 if ( [listObject isKindOfClass:[AIMetaContact class]] ) {
245                         listContact = [(AIMetaContact *)listObject preferredContactWithCompatibleService:service];
246                 } else if ( [listObject isKindOfClass:[AIListContact class]] ) {
247                         if ([[listObject service] isEqualTo:service]) {
248                                 listContact = (AIListContact *)listObject;
249                         }
250                 }                               
251                 
252                 if ( listContact && [listContact online] ) {
253                         return listContact;
254                 }
255         }
256         
257         return nil;
260 // Tests if dragged objects are valid for this account
261 // Must be called by explicitly the subclass
262 - (NSDragOperation)doDraggingEntered:(id <NSDraggingInfo>)sender
263 {       
264         // Test whether this drag item is acceptable
265         NSPasteboard *pboard = [sender draggingPasteboard];
266         
267         // Are there list objects being dragged?
268         if ([pboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObject"]]) {
269                 
270                 // If so, get the ID's
271                 if ([[pboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObjectUniqueIDs"]] isEqualToString:@"AIListObjectUniqueIDs"]) {
272                         NSArray                 *dragItemsUniqueIDs;
273                         NSString                *uniqueID;
274                         NSEnumerator    *enumerator;
275                         
276                         dragItemsUniqueIDs = [pboard propertyListForType:@"AIListObjectUniqueIDs"];
277                         
278                         enumerator = [dragItemsUniqueIDs objectEnumerator];
279                         while ((uniqueID = [enumerator nextObject])) {
280                                 
281                                 // Is there a contact with our service?
282                                 if ( [self validContact:uniqueID withService:[account service]] ) {
283                                         
284                                         //if ([[view window] firstResponder] != textField_inviteUsers)
285                                         //      [[view window] makeFirstResponder:textField_inviteUsers];
286                                         return NSDragOperationGeneric;
287                                 }
288                         }
289                 }
290         }
291         
292         //if we reach this point, no valid contacts were dragged
293         return NSDragOperationNone;
296 // Accepts list contacts being dragged over theField and adds their ID's to the field in a nice manner
297 // Note: subclasses must call this explicitly
298 - (BOOL)doPerformDragOperation:(id <NSDraggingInfo>)sender toField:(NSTextField *)theField
299 {       
300         NSPasteboard *pboard = [sender draggingPasteboard];
301         
302         // Were ListObjects dragged?
303         if ([pboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObject"]]) {
304                 
305                 // If so, get the unique ID's
306                 if ([[pboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObjectUniqueIDs"]] isEqualToString:@"AIListObjectUniqueIDs"]) {
307                         NSArray                 *dragItemsUniqueIDs;
308                         NSString                *uniqueID;
309                         AIListObject    *listObject;
310                         AIListContact   *listContact;
311                         NSEnumerator    *enumerator;
312                         
313                         dragItemsUniqueIDs = [pboard propertyListForType:@"AIListObjectUniqueIDs"];
314                         
315                         enumerator = [dragItemsUniqueIDs objectEnumerator];
316                         while ((uniqueID = [enumerator nextObject])) {
317                                 NSString *oldValue = [theField stringValue];
318                                 listObject = [[adium contactController] existingListObjectWithUniqueID:uniqueID];
319                                 
320                                 // Get contacts with our service
321                                 // (May not be necessary, as we reject ungood contacts in the dragging entered phase)
322                                 if ((listContact = [self validContact:uniqueID withService:[account service]])) {
323                                         
324                                         // Add a comma for prettiness if need be
325                                         if ( [oldValue length] && ![[oldValue substringFromIndex:([oldValue length]-1)] isEqualToString:@","] ) {
326                                                 oldValue = [oldValue stringByAppendingString:@", "];
327                                                 [theField setStringValue:oldValue];
328                                         }
329                                         [theField setStringValue:[oldValue stringByAppendingString:[listContact displayName]]];
330                                 }
331                         }
332                 }
333         }
334         return YES;
337 #pragma mark Delegate handling
338 - (void)setDelegate:(id)inDelegate
340         delegate = inDelegate;
342 - (id)delegate;
344         return delegate;
347 #pragma mark Roomlist Delegate
348 - (void)setSharedChatInstance:(id)newInstance
350         NSLog(@"sharedChatInstance: %@",newInstance);
351         sharedChatInstance = newInstance;
354 -(id)sharedChatInstance
356         return sharedChatInstance;
360 @end